/**
 * @author yhanger
 */
var undefined;
var yhang = window.yhang = window.$ = function(dom, parent){
    return new yhang.dom(dom, parent);
};

yhang.extend = function(from, to){
    to = to || yhang;
    for (var p in from) {
        to[p] = from[p];
    }
};

yhang.extend({
    version: '1.0.0',
    release: '20090725',
    author: 'yhanger',
    each: function(obj, callback, args){
        var len = obj.length;
        if (len === undefined) {
            for (var key in obj) {
                if (callback.call(obj[key], key, obj[key], args) === false) {
                    break;
                }
            }
        }
        else {
            for (var i = 0; i < len && callback.call(obj[i], i, obj[i], args) !== false; i++) {
            }
        }
        return obj;
    },
    toArray: function(obj){
        var arr = [];
        yhang.each(obj, function(key, val){
            arr.push(val);
        });
        return arr;
    },
    getArray: function(arr, fn){
        var ret = [];
        yhang.each(arr, function(key, val){
            var retFun = fn(key, val);
            if (undefined !== retFun) {
                ret.push(retFun);
            }
        });
        return ret;
    },
    search: function(obj, fn){
        var ret = undefined;
        yhang.each(obj, function(k, v){
            ret = fn(k, v);
            if (ret !== undefined) {
                return false;
            }
        });
        return ret;
    },
    indexOf: function(obj, search){
        return yhang.search(obj, function(k, v){
            if (v === search) {
                return k;
            }
        });
    },
	isArray: function(obj) {
		return Object.prototype.toString.call(obj) === "[object Array]";
	}
});

yhang.dom = function(selector, parent){
    selector = selector || document;
    parent = document.getElementById(parent) || document;
    //domElement
    if (selector.nodeType) {
        this[0] = dom;
        this.length = 1;
        return this;
    }
    
    //string
    if (typeof selector == 'string') {
        //*
        if (selector === '*') {
            return yhang.toArray(parent.getElementsByTagName('*'));
        }
        
        var match;
        //#id
        match = /^#([\w-]+)$/.exec(selector);
        if (match) {
            this[0] = document.getElementById(match[1]);
            this.length = 1;
            return this;
        }
        
        //tag
        match = selector.match(/^[a-zA-Z]+$/);
        if (match) {
            return this.setArray(yhang.toArray(parent.getElementsByTagName(match[0])));
        }
        
        //.class
        match = /^\.([\w-]+)$/.exec(selector);
        if (match) {
            var elems = parent.getElementsByTagName('*');
            return this.setArray(yhang.getArray(elems, function(key, val){
                if (val.className === match[1]) {
                    return val;
                }
            }));
        }
        
        //tag.class
        match = /^([a-zA-Z]+)\.([\w-]+)$/.exec(selector);
        if (match) {
            var elems = parent.getElementsByTagName(match[1]);
            return this.setArray(yhang.getArray(elems, function(key, val){
                if (val.className === match[2]) {
                    return val;
                }
            }));
        }
    }
};

yhang.dom.prototype = {
    yhang: 1,
    len: function(){
        return this.length;
    },
    setArray: function(arr){
        this.length = 0;
        Array.prototype.push.apply(this, arr);
        return this;
    },
    get: function(num){
        return num === undefined ? this[0] : this[num >= 0 ? num : this.length + num];
    },
    each: function(callback, args){
        return yhang.each(this, callback, args);
    },
    index: function(elems){
        return yhang.indexOf(this, elems && elems.yhang ? elems[0] : elems);
    },
    html: function(val){
        if (val === undefined) {
            return this[0].innerHTML;
        }
        else {
            this.each(function(k, v){
                v.innerHTML = val;
            });
			return this;
        }
    },
	val: function(val){
		if (val === undefined) {
			return this[0];
		} else {
			this.each(function(k, v){
				v.value = val;
			});
			return this;
		}
	}
    //to be concituned
};
